//
// Created by YH-Mac on 2021/3/24.
//

#include "c_api.h"
#include "../FaceDetector/FaceDetector.h"
#include "../common/common.h"

long InitDetectorSession(char *models_path) {
    std::string dir(models_path);
    auto *detector = new Detector(dir);
    return (long) detector;
}

void FaceDetection(long session, char *image, int w, int h, int level, float **output, int *outputNum) {
    auto *detector = (Detector *) session;
    cv::Mat img(h, w, CV_8UC3, image);
    cv::Mat img_scale;
    float scale = 1;
    int max = h;
    if (w > h) {
        max = w;
    }
    scale = float(level) / float(max);
    cv::resize(img, img_scale, cv::Size(img.cols * scale, img.rows * scale));
    std::vector<bbox> faceInfo;
    detector->Detect(img_scale, faceInfo);
    std::vector<bbox> ori_boxes;
    for (int j = 0; j < faceInfo.size(); ++j) {
        bbox ori_box = faceInfo[j];
        ori_box.x1 = faceInfo[j].x1 / scale;
        ori_box.y1 = faceInfo[j].y1 / scale;
        ori_box.x2 = faceInfo[j].x2 / scale;
        ori_box.y2 = faceInfo[j].y2 / scale;
        ori_box.point[0]._x = faceInfo[j].point[0]._x / scale;
        ori_box.point[0]._y = faceInfo[j].point[0]._y / scale;
        ori_box.point[1]._x = faceInfo[j].point[1]._x / scale;
        ori_box.point[1]._y = faceInfo[j].point[1]._y / scale;
        ori_box.point[2]._x = faceInfo[j].point[2]._x / scale;
        ori_box.point[2]._y = faceInfo[j].point[2]._y / scale;
        ori_box.point[3]._x = faceInfo[j].point[3]._x / scale;
        ori_box.point[3]._y = faceInfo[j].point[3]._y / scale;
        ori_box.point[4]._x = faceInfo[j].point[4]._x / scale;
        ori_box.point[4]._y = faceInfo[j].point[4]._y / scale;
        ori_boxes.push_back(ori_box);
    }
    *outputNum = faceInfo.size();
    *output = new float[ori_boxes.size() * 15];
    float *data = *output;
    for (int i = 0; i < ori_boxes.size(); i++) {
        data[i * 15 + 0] = ori_boxes[i].s;
        data[i * 15 + 1] = ori_boxes[i].x1;
        data[i * 15 + 2] = ori_boxes[i].y1;
        data[i * 15 + 3] = ori_boxes[i].x2;
        data[i * 15 + 4] = ori_boxes[i].y2;
        data[i * 15 + 5] = ori_boxes[i].point[0]._x;
        data[i * 15 + 6] = ori_boxes[i].point[0]._y;
        data[i * 15 + 7] = ori_boxes[i].point[1]._x;
        data[i * 15 + 8] = ori_boxes[i].point[1]._y;
        data[i * 15 + 9] = ori_boxes[i].point[2]._x;
        data[i * 15 + 10] = ori_boxes[i].point[2]._y;
        data[i * 15 + 11] = ori_boxes[i].point[3]._x;
        data[i * 15 + 12] = ori_boxes[i].point[3]._y;
        data[i * 15 + 13] = ori_boxes[i].point[4]._x;
        data[i * 15 + 14] = ori_boxes[i].point[4]._y;
    }

}

void ReleaseDetectorSession(long session) {
    auto *detector = (Detector *) session;
    delete detector;
}

void FreeFloat(float **memblock) {
    delete[]*memblock;
}